package com.turing.post.account.impl;

import java.math.BigInteger;
import java.util.List;

import javax.ejb.EJB;
import javax.ejb.Local;
import javax.ejb.Remote;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import com.turing.post.account.util.SubAccount;
import com.turing.post.account.util.SubAccountDao;
import com.turing.post.cardmanagement.util.ActivateCardDao;
import com.turing.post.util.GeneralDao;
import com.turing.post.util.PCPSApplicationException;
import com.turing.post.util.PCPSWebInput;

@Stateless(mappedName = "account.impl.SubAccountDaoImpl")
@Remote
@Local
public class SubAccountDaoImpl implements SubAccountDao {

	@EJB(mappedName = "cardmanagement.impl.ActivateCardDaoImpl")
	private ActivateCardDao activateCardDaoImpl;

	/**
	 * 实体管理器
	 * 
	 * @see javax.persistence.EntityManager
	 */
	@PersistenceContext
	protected EntityManager _em;

	/**
	 * 插入子帐户记录
	 * 
	 * @param sac
	 * @throws PCPSApplicationException
	 */
	public void insert(SubAccount sac) throws PCPSApplicationException {
		GeneralDao.insert(_em, sac);
	}

	/**
	 * 更新子帐户记录
	 * 
	 * @param sac
	 * @throws PCPSApplicationException
	 */
	public void update(SubAccount sac) throws PCPSApplicationException {
		GeneralDao.update(_em, sac);
	}

	/**
	 * 根据子帐号号检索子帐户
	 */
	public SubAccount getSubAccountBySubAccNo(BigInteger subAccNo) {
		return _em.find(SubAccount.class, subAccNo);
	}

	/**
	 * 记录锁定,准备更新
	 * 
	 * @param subAccNo
	 */
	@SuppressWarnings("unchecked")
	public SubAccount getSubAccountBySubAccNoForUpdate(BigInteger subAccNo) {
		Query query = _em
				.createNativeQuery(
						"select t.* from SubAccount t where t.subAccNo = ?1 for update",
						SubAccount.class);
		query.setParameter(1, subAccNo);
		List<SubAccount> li = query.getResultList();
		if (li == null || li.size() != 1)
			return (null);

		SubAccount ac = li.get(0);
		_em.refresh(ac);

		return getSubAccountBySubAccNo(ac.getSubAccNo());
	}

	/**
	 * 计算某主帐户下所有子帐户的余额
	 * 
	 * @param masterAccNo
	 * @return
	 */
	public BigInteger getAllSubAccountBalanceByMasterAccNo(
			BigInteger masterAccNo) {
		Query query = _em
				.createNativeQuery("select sum(t.Balance) from SubAccount t where t.masterAccNo = ?1");
		query.setParameter(1, masterAccNo);
		if (query.getSingleResult() == null)
			return BigInteger.ZERO;
		return new BigInteger(query.getSingleResult().toString());
	}

	/**
	 * 获取某主帐户下可以支付的所有子帐户
	 * 
	 * @param masterAccNo
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<SubAccount> getAllSubAccountForPaidByMasterAccNo(
			BigInteger masterAccNo) {
		Query query = _em
				.createNativeQuery(
						"select t.* from SubAccount t where t.masterAccNo = ?1 and balance > 0",
						SubAccount.class);
		query.setParameter(1, masterAccNo);
		return query.getResultList();
	}

	/**
	 * 获取某主帐户下可以支付的所有子帐户
	 * 
	 * @param masterAccNo
	 * @return
	 */
	@SuppressWarnings("unchecked")
	@Override
	public List<SubAccount> getSubAccountListByMasterAccNo(
			BigInteger masterAccNo) {
		Query query = _em.createNativeQuery(
				"select t.* from SubAccount t where t.masterAccNo = ?1",
				SubAccount.class);
		query.setParameter(1, masterAccNo);
		return query.getResultList();
	}

	/**
	 * 根据卡号或卡序号获取子账户列表
	 */
	@SuppressWarnings("unchecked")
	@Override
	public List<SubAccount> getSubAccListByCardNoOrCardSeqNo(
			PCPSWebInput webInput, String cardNo) {
		if (!activateCardDaoImpl.checkOperIsInIssueCompany(webInput
				.getOperBranchNo(), cardNo)) {
			return null;
		}
		Query query = _em
				.createNativeQuery(
						"select t.* "
								+ "from subaccount t,activatecard a,masteraccount m "
								+ "where a.masteraccno=m.masteraccno and m.masteraccno=t.masteraccno "
								+ "and (a.cardno= ?1 or a.cardseqno= ?2)",
						SubAccount.class);
		query.setParameter(1, cardNo);
		query.setParameter(2, cardNo);
		return query.getResultList();
	}
}
